home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / General / CW TCL port package / Template Munger / Source / MakeTemplate.c < prev    next >
Text File  |  1994-05-30  |  10KB  |  390 lines

  1. /*
  2. ** MakeTemplate.c
  3. */
  4.  
  5. short def_vRef = 0;                // folder for definition (input) files
  6. long def_parID = 0;
  7. short def_fRef = 0;                // file reference for current definition  file
  8. Handle defText;                    // handle for definition  file
  9.  
  10. short out_vRef = 0;                // folder for output files
  11. long out_parID = 0;
  12. short out_fRef = 0;                // file reference for current output file
  13. Handle outText;                    // handle for new output file
  14.  
  15. extern Str63 outFileName;        // name of template macro file name (typically ___.tm.h)
  16. extern Str63 defnFileName;        // name of template definition file name (typically ___.tem)
  17. extern char ch_type [256];
  18.  
  19. Str255 junkBfr;                // junk characters buffer
  20. Boolean hadToken;                // true if a token occurred on this line
  21.  
  22. Boolean inTemplateDefn;            // true if defining (rather than declaring) template
  23.  
  24. char outClass[255];                // class of template we're building
  25. char wildcard[255];                // class of wildcard we're defining (macro argument)
  26. short tokenState;                // state of token parser
  27.     // 0 = normal operation
  28.     // 1 = encountered 'template', expecting '<'
  29.     // 2 = encountered 'template <', expecting 'class'
  30.     // 3 = encountered 'template <class', expecting (type)
  31.     // 4 = encountered 'template <class (type)', expecting '>'
  32.     // 5 = encountered 'template <class (type)>', expecting 'class' or function type
  33.     // 6 = encountered 'template <class (type)> class', expecting (class)
  34.                 // then cycles back to 0
  35.     // 10 = encountered '<', check for type
  36.     // 11 = encountered '< (type)', expecting '>'
  37.     // 20 = encountered (class), name of base class, expecting '(' – constructor/destructor
  38.  
  39.  
  40. void OutCStr(char* str);
  41. void OutPStr(unsigned char* str);
  42. extern void ErrMsg ( unsigned char * why , unsigned char * file , short code );
  43.  
  44.  
  45. Boolean OpenOutfile()
  46. {
  47.     OSErr err;
  48.  
  49.     err = HCreate(out_vRef, out_parID, outFileName, 'MPCC', 'TEXT');
  50.     if (err == -48) {            // duplicate file name, delete old file (dangerous... I know!)
  51.         err = HDelete(out_vRef, out_parID, outFileName);
  52.         if (!err) {
  53.             err = HCreate(out_vRef, out_parID, outFileName, 'MPCC', 'TEXT');
  54.         }
  55.     }
  56.  
  57.     if (err) {
  58.         ErrMsg("\pCreating", outFileName, err);
  59.         return true;
  60.     }
  61.  
  62.     err = HOpenDF ( out_vRef , out_parID , outFileName , fsRdWrPerm , & out_fRef ) ;
  63.     if ( err ) {
  64.         ErrMsg ( "\pOpening" , outFileName , err ) ;
  65.         return true;
  66.     }
  67.     outText = NewHandle (0) ;
  68.     if ( ! outText ) {
  69.         ErrMsg ( "\pAllocating" , outFileName , MemError ( ) ) ;
  70.         FSClose ( out_fRef ) ;
  71.         return true;
  72.     }
  73.     
  74.     OutCStr("// ");
  75.     OutPStr(outFileName);
  76.     OutCStr("\r//\r// Macro template file\r// Generated by Template Munger\r\r");
  77.  
  78.     junkBfr[0] = 0;
  79.     outClass[0] = 0;
  80.     wildcard[0] = 0;
  81.     hadToken = false;
  82.     inTemplateDefn = false;
  83.     
  84.     return false;
  85.  
  86. }
  87.  
  88.  
  89. void CloseOutfile()
  90. {
  91.     OSErr err;
  92.     long size ;
  93.  
  94.     size = GetHandleSize ( outText ) ;
  95.     err = SetEOF ( out_fRef , size ) ;
  96.     if ( ! err ) {
  97.         err = SetFPos ( out_fRef , fsFromStart , 0L ) ;
  98.     }
  99.     if ( err ) {
  100.         ErrMsg ( "\pFinishing" , outFileName , err ) ;
  101.         FSClose ( out_fRef ) ;
  102.         DisposeHandle ( outText ) ;
  103.         return ;
  104.     }
  105.     HLock ( outText ) ;
  106.     err = FSWrite ( out_fRef , & size , * outText ) ;
  107.     if ( err ) {
  108.         ErrMsg ( "\pWriting" , outFileName , err ) ;
  109.         FSClose ( out_fRef ) ;
  110.         DisposeHandle ( outText ) ;
  111.         return ;
  112.     }
  113.     err = FSClose ( out_fRef ) ;
  114.     if ( ! err ) {
  115.         err = FlushVol ( NULL , out_vRef ) ;
  116.     }
  117.     DisposeHandle ( outText ) ;
  118.     if ( err ) {
  119.         ErrMsg ( "\pClosing" , outFileName , err ) ;
  120.     }
  121. }
  122.  
  123.  
  124. void OutCStr(char* str)
  125. {
  126.     long len = 0;
  127.     char* p = str;
  128.     
  129.     while (*p++)
  130.         len++;
  131.     PtrAndHand(str, outText, len);
  132. }
  133.  
  134. void OutPStr(unsigned char* str)
  135. {
  136.     long len = *str;
  137.     PtrAndHand(str+1, outText, len);
  138. }
  139.  
  140. void OutJunkChar(char theChar)
  141. {
  142.     if ((tokenState == 10) && ((theChar != ' ') && (theChar != '\t'))) {
  143.         junkBfr[++junkBfr[0]] = '<';            // make sure that <> or <= doesn't trigger template expansion
  144.         tokenState = 0;
  145.     }
  146.     junkBfr[++junkBfr[0]] = theChar;
  147.     if (junkBfr[0] > 200) {
  148.         OutPStr(junkBfr);
  149.         junkBfr[0] = 0;
  150.     }
  151. }
  152.  
  153. Boolean OutToken(char* theToken)
  154. {
  155.     Boolean tokValid = true;                    // set to false if invalid token for context
  156.     if ((junkBfr[0]) && (tokenState == 0)) {
  157.         OutPStr(junkBfr);
  158.         junkBfr[0] = 0;
  159.     }
  160.     
  161.     hadToken = true;
  162.     switch (tokenState) {
  163.         case 0:                            // normal operation: check for keywords
  164.             if (!strcmp(theToken, "template")) {
  165.                 tokenState = 1;                // found a template declaration, parse it
  166.                 break;
  167.             }
  168.             if (!strcmp(theToken, "<")) {
  169.                 tokenState = 10;            // might be a reference to the template, parse it
  170.                 if (junkBfr[0]) {            // get other characters out in proper sequence
  171.                     OutPStr(junkBfr);
  172.                     junkBfr[0] = 0;
  173.                 }
  174.                 break;
  175.             }
  176.             if (!strcmp(theToken, outClass)) {    // template class name, see if it's constructor/destructor
  177.                 tokenState = 20;
  178.                 break;
  179.             }
  180.             OutCStr(theToken);                // neither of the above, just copy it
  181.             break;
  182.             
  183.         case 1:                            // got 'template', expect '<'
  184.             if (strcmp(theToken, "<")) {
  185.                 tokValid = false;
  186.                 tokenState = 0;
  187.                 OutCStr("template");        // just copy the invalid stuff to file
  188.                 OutToken(theToken);
  189.                 break;
  190.             }
  191.             tokenState++;                    // valid input, continue chain
  192.             break;
  193.  
  194.         case 2:                            // got 'template <', expect 'class'
  195.             if (strcmp(theToken, "class")) {
  196.                 tokValid = false;
  197.                 tokenState = 0;
  198.                 OutCStr("template <");        // just copy the invalid stuff to file
  199.                 OutToken(theToken);
  200.                 break;
  201.             }
  202.             tokenState++;                    // valid input, continue chain
  203.             break;
  204.         
  205.         case 3:                            // got 'template <class', expect (type)
  206.             if (ch_type[theToken[0]] != 4) {    // first character must be alpha
  207.                 tokValid = false;
  208.                 tokenState = 0;
  209.                 OutCStr("template <class ");    // just copy the invalid stuff to file
  210.                 OutToken(theToken);
  211.                 break;
  212.             }
  213.             strcpy(wildcard, theToken);        // keep this thing around
  214.             tokenState++;                    // valid input, continue chain
  215.             break;
  216.         
  217.         case 4:                            // got 'template <class (type)', expect '>'
  218.             if (strcmp(theToken, ">")) {
  219.                 tokValid = false;
  220.                 tokenState = 0;
  221.                 OutCStr("template <class ");    // just copy the invalid stuff to file
  222.                 OutCStr(wildcard);
  223.                 OutToken(theToken);
  224.                 break;
  225.             }
  226.             tokenState++;                    // valid input, continue chain
  227.             break;
  228.         
  229.         case 5:                            // got 'template <class (type)>', expect 'class'  or function type
  230.             if (inTemplateDefn) {
  231.                 tokenState = 0;                // just dump the 'template <class (type)>' line
  232.                 junkBfr[0] = 0;
  233.                 OutToken(theToken);
  234.                 break;
  235.             } else {
  236.                 if (strcmp(theToken, "class")) {    // declaring class, expect 'class' only
  237.                     tokValid = false;
  238.                     tokenState = 0;
  239.                     OutCStr("template <class ");    // just copy the invalid stuff to file
  240.                     OutCStr(wildcard);
  241.                     OutCStr(">");
  242.                     OutToken(theToken);
  243.                     break;
  244.                 }
  245.                 tokenState++;                    // valid input, continue chain
  246.                 break;
  247.             }
  248.         
  249.         case 6:                            // got 'template <class (type)> class', expect '(type)'
  250.             if (ch_type[theToken[0]] != 4) {    // first character must be alpha
  251.                 tokValid = false;
  252.                 tokenState = 0;
  253.                 OutCStr("template <class ");    // just copy the invalid stuff to file
  254.                 OutCStr(wildcard);
  255.                 OutToken(theToken);
  256.                 break;
  257.             }
  258.             strcpy(outClass, theToken);        // keep this thing around
  259.             
  260.             OutCStr("\r#define TM_DECLARE_");    // valid input, write macro header
  261.             OutCStr(outClass);
  262.             OutCStr("(");
  263.             OutCStr(wildcard);
  264.             OutCStr(") \\\rclass ");
  265.             OutCStr(outClass);
  266.             OutCStr("_ ## ");
  267.             OutCStr(wildcard);
  268.             
  269.             junkBfr[0] = 0;                    // clear junk buffer
  270.             tokenState = 0;                    // resume normal operation
  271.             break;
  272.         
  273.         case 10:                            // got '<', might get (wildcard type)
  274.             if (strcmp(theToken, wildcard)) {
  275.                 tokenState = 0;                // nope… just treat it like anything else
  276.                 OutCStr("<");                // make sure the '<' charater gets out properly
  277.                 OutToken(theToken);            // and print this other token
  278.                 break;
  279.             }
  280.             tokenState++;                    // valid input, continue chain
  281.             break;
  282.         
  283.         case 11:                            // got '< (wildcard)', expecting '>'
  284.             if (strcmp(theToken, ">")) {
  285.                 tokValid = false;
  286.                 tokenState = 0;
  287.                 OutCStr("<");                // just copy the invalid stuff to file
  288.                 OutCStr(wildcard);
  289.                 OutToken(theToken);
  290.                 break;
  291.             }
  292.             
  293.             OutCStr("_ ## ");                // was valid, substitute template expansion
  294.             OutCStr(wildcard);
  295.             junkBfr[0] = 0;
  296.             tokenState = 0;                    // back to normal
  297.             break;
  298.  
  299.         case 20:                            // got class name, look for '('
  300.             if (!strcmp(theToken, "(")) {
  301.                 OutCStr(outClass);            // found '(', substitute expanded constructor/destructor name
  302.                 OutCStr("_ ## ");
  303.                 OutCStr(wildcard);
  304.             }
  305.             else
  306.                 OutCStr(outClass);            // no '(' found, just print it as is
  307.             tokenState = 0;                    // print the stuff
  308.             OutToken(theToken);
  309.             break;
  310.  
  311.         default:                            // something broke!
  312.             Message("\rInternal error");
  313.             tokenState = 0;
  314.             OutToken(theToken);
  315.             break;
  316.  
  317.     }
  318.     
  319.     hadToken = true;
  320.     return tokValid;                        // token was valid…
  321.  
  322. }
  323.  
  324. void OutNewLine()
  325. {
  326.     short i;
  327.     char* p;
  328.     
  329.     if (tokenState != 0) {
  330.         OutJunkChar(' ');                        // ignore new lines in the midst of template declarations
  331.         return;
  332.     }
  333.         
  334.     i = junkBfr[0]+1;
  335.     p = (char*) &junkBfr[i];                        // strip all trailing spaces from "junk buffer"
  336.     while (--p, --i) {
  337.         if ((*p != ' ') && (*p != '\t'))
  338.             break;                            // non-blank, must print it
  339.         else
  340.             junkBfr[0]--;                        // remove this character
  341.     }
  342.  
  343.     if ((!hadToken) && (!junkBfr[0]))                // completely blank line, skip it
  344.         return;
  345.  
  346.     if (junkBfr[0]) {
  347.         OutPStr(junkBfr);
  348.         junkBfr[0] = 0;
  349.     }
  350.     hadToken = false;
  351.     OutCStr(" \\\r");                            // be sure to continue macro definition
  352. }
  353.  
  354. void EndTemplateDeclaration()
  355. {
  356.     if (junkBfr[0]) {
  357.         OutPStr(junkBfr);
  358.         junkBfr[0] = 0;
  359.     }
  360.     OutCStr("};\r");
  361. }
  362.  
  363. void StartTemplateDefn()
  364. {
  365.     if (junkBfr[0]) {
  366.         OutPStr(junkBfr);
  367.         junkBfr[0] = 0;
  368.     }
  369.  
  370.     OutCStr("\r\r\r#define TM_DEFINE_");        // write macro header – using same class name
  371.     OutCStr(outClass);
  372.     OutCStr("(");
  373.     OutCStr(wildcard);
  374.     OutCStr(") \\\r");
  375.     
  376.     junkBfr[0] = 0;                            // clear junk buffer
  377.     tokenState = 0;                            // resume normal operation
  378.     inTemplateDefn = true;                    // …except we want to allow template function definitions
  379. }
  380.  
  381.  
  382. void EndTemplateDefn()
  383. {
  384.     if (junkBfr[0]) {
  385.         OutPStr(junkBfr);
  386.         junkBfr[0] = 0;
  387.     }
  388.     OutCStr("\r\r");
  389. }
  390.